/*
1.浮点数各个类型的所占字节大小：
float的字节：4
double的字节：8
long double的字节：16

2.浮点数的表示形式：
0.008在计算机中存储为： 0.008000
8E-3在计算机中存储为： 0.008000
8000在计算机中存储为： 8000.000000
8E+3在计算机中存储为： 8000.000000

*** float的精度为6位小数，double的精度为15-16位，long double的精度大于等于double

3.绝大多数的浮点数是不能精确表示的：
以float型                存储1.12345678901234567890数据，               实际存储值为：1.123456835746765136718750000000，只有前6位正常表示
以double型             存储1.12345678901234567890数据，              实际存储值为：1.123456789012345691247674039914，只有前16位正常表示
以long double型存储1.12345678901234567890数据，              实际存储值为：1.123456789012345691247674039914，只有前16位正常表示


4. 浮点数的比较（注意：只有数字形式如0.8，默认0.8是double类型；关注浮点数能不能在计算机中精确表示）
float类型的2.2: 2.200000047683715820312500000000
double类型的2.2: 2.200000000000000177635683940025
fa != 2.2,此时fa是float类型的2.2,在乘2取整表示小数部分时无法精确表示，所以float和double都无法正确存储到计算机中。再由于两种类型精度不同，故值不同
float类型的2.2: 2.200000047683715820312500000000
float类型的2.2: 2.200000047683715820312500000000
fa == 2.2f,此时fa是float类型的2.2,在乘2取整表示小数部分时无法精确表示，所以float无法正确存储到计算机中。但由于两者精度相同，故值相同
float类型的2.25: 2.250000000000000000000000000000
double类型的2.25: 2.250000000000000000000000000000
fb == 2.25,此时fb是float类型的2.25,在乘2取整表示小数部分时可以精确表示，所以float和double可以正确存储到计算机中。尽管两种类型精度不同，但值相同

5. 浮点数比较案例2：
double类型1.0存储为：1.000000000000000000000000000000
double类型0.9存储为：0.900000000000000022204460492503
double类型1.0-0.9存储为：0.099999999999999977795539507497
double类型0.1存储为：0.100000000000000005551115123126
(1.0-0.9) != 0.1,因为两边均不能正常表示

6.实际中浮点数该如何比较（采用自定义精度的形式）
fabs((1.0-0.9)-0.1) < 0.00000000000001,此时式子就是成立的


7.比较下不同的输出控制下打印情况：
double fff = 3.141592;
采用lf的输出模式：3.141592
采用.30f的输出模式：3.141592000000000162174274009885


*/
#include<stdio.h>
#include<math.h>
int main(){
	printf("浮点数各个类型的所占字节大小：\n");
	printf("float的字节：%ld\n" , sizeof(float));
	printf("double的字节：%ld\n" , sizeof(double));
	printf("long double的字节：%ld\n" , sizeof(long double));
	
	printf("浮点数的表示形式：\n");
	float f1 = 0.008;
	float f2 = 8E-3;
	float f3 = 8000;
	float f4 = 8E+3;
	printf("0.008在计算机中存储为： %f\n" , f1);
	printf("8E-3在计算机中存储为： %f\n" , f2);
	printf("8000在计算机中存储为： %f\n" , f3);
	printf("8E+3在计算机中存储为： %f\n" , f4);
	
	float a = 1.12345678901234567890;
	double b = 1.12345678901234567890;
	long double c = 1.12345678901234567890;
	printf("绝大多数的浮点数是不能精确表示的：\n");
	printf("以float型存储1.12345678901234567890数据，实际存储值为：%.30f，只有前6位正常表示\n",a);
	printf("以double型存储1.12345678901234567890数据，实际存储值为：%.30lf，只有前16位正常表示\n",b);	
	printf("以long double型存储1.12345678901234567890数据，实际存储值为：%.30Lf，只有前16位正常表示\n",c);
	
	float fa = 2.2;
	if(fa != 2.2){
		printf("float类型的2.2: %.30f\n",fa);
		printf("double类型的2.2: %.30lf\n",2.2);
		printf("fa != 2.2,此时fa是float类型的2.2,在乘2取整表示小数部分时无法精确表示，所以float和double都无法正确存储到计算机中。再由于两种类型精度不同，故值不同\n");
	}
	if(fa == 2.2f){
		printf("float类型的2.2: %.30f\n",fa);
		printf("float类型的2.2: %.30f\n",2.2f);
		printf("fa == 2.2f,此时fa是float类型的2.2,在乘2取整表示小数部分时无法精确表示，所以float无法正确存储到计算机中。但由于两者精度相同，故值相同\n");
	}
	float fb = 2.25;
	if(fb == 2.25){
		printf("float类型的2.25: %.30f\n",fb);
		printf("double类型的2.25: %.30lf\n",2.25);
		printf("fb == 2.25,此时fb是float类型的2.25,在乘2取整表示小数部分时可以精确表示，所以float和double可以正确存储到计算机中。尽管两种类型精度不同，但值相同\n");
	}	
	
	double dd = 1.0;
	double bb = 0.9;
	printf("double类型1.0存储为：%.30f\n",dd);
	printf("double类型0.9存储为：%.30f\n",bb);
	printf("double类型1.0-0.9存储为：%.30f\n",dd-bb);
	printf("double类型0.1存储为：%.30f\n",0.1);
	if((dd-bb) != 0.1){
		printf("(1.0-0.9) != 0.1,因为两边均不能正常表示\n");
	}
	
	if(fabs((dd-bb)-0.1) < 0.00000000000001){
		printf("fabs((1.0-0.9)-0.1) < 0.00000000000001,此时式子就是成立的\n");
	}
	
	double fff = 3.141592;
	printf("比较下不同的输出控制下打印情况：\n");
	printf("采用lf的输出模式：%lf\n",fff);
	printf("采用.30f的输出模式：%.30f\n",fff);
	
	return 0;
}
